package
{
	import flash.events.Event;
	
	import org.flixel.*;

	public class MyPuzzles extends FlxState
	{
		private const CONTAINER_WIDTH:int = FlxG.width - 250;
		private const CONTAINER_HEIGHT:int = FlxG.height - 100;
		private const CONTAINER_START_X:int = (FlxG.width - CONTAINER_WIDTH) / 2 - 100;
		private const CONTAINER_START_Y:int = ((FlxG.height - CONTAINER_HEIGHT)/2) + 20;
		private var container:FlxSprite;
		private var body:FlxSprite;
		private var listings:FlxGroup;
		
		// footer
		private var pageNum:FlxText;
		private var prevPage:FlxText;
		private var nextPage:FlxText;
		private var currentPage:int;
		
		// other stuffs
		private var loadingText:FlxText;
		private var loadingSprite:LoadingIndicator;
		private var emptySign:FlxText;
		private var exitButton:FlxSprite;
		
		private var loading:Boolean;
		
		private var numMaps:int;
		
		private var listingArray:Array;
		private var challenge1:FlxSprite;
		private var challenge2:FlxSprite;
		private var challenge3:FlxSprite;
		private var mapID1:int;
		private var mapID2:int;
		private var mapID3:int;
		protected var challengePopup:ChallengeFriendsComponent;
		protected var modalPopup:Boolean;
		
		public function MyPuzzles()
		{
			super();
			
			// Log that the user has entered the puzzle loader!
			Elemental.Log.startDquest(Logging.PUZZLE_LOADER);
			
			initLayout();

			currentPage = 1;
			loading = false;
			
			requestData();
		}
		
		
		/**
		 * Draw the container, tabs, exit button, etc.
		 */
		public function initLayout():void {
			add(new FlxSprite(0,0, Res.bg));
			
			container = new FlxSprite();
			container.makeGraphic(CONTAINER_WIDTH, CONTAINER_HEIGHT);
			container.drawRect(0, 0, CONTAINER_WIDTH, CONTAINER_HEIGHT, 0x590E04);
			container.x = CONTAINER_START_X;
			container.y = CONTAINER_START_Y;
			add(container);
			
			body = new FlxSprite();
			body.makeGraphic(CONTAINER_WIDTH - 50, CONTAINER_HEIGHT-50, 0x000000, true);
			body.drawRect(0, 0, CONTAINER_WIDTH - 50, CONTAINER_HEIGHT-50, 0xD69F98);
			body.x = container.x + 25;
			body.y = container.y + 25;
			add(body);
			
			exitButton = new FlxSprite(0, 0, Res.ExitButton);
			exitButton.x = FlxG.width - exitButton.width - 5;
			exitButton.y = 5;
			add(exitButton);
			
			createPageFooter();
			
			listings = new FlxGroup();
			add(listings);
			
			loadingText = new FlxText(0, 0, body.width, "Loading puzzles ...", false);
			loadingText.setFormat("Courier New", 24, 0x000000, "center", 0, true);
			loadingText.x = body.x + (body.width - loadingText.width)/2;
			loadingText.y = body.y + (body.height - loadingText.height)/2 - 20;
			
			loadingSprite = new LoadingIndicator(0, 0);
			loadingSprite.x = body.x + (body.width - loadingSprite.width)/2;
			loadingSprite.y = loadingText.y + loadingText.height + 10;
			
			emptySign = new FlxText(0, 0, body.width, "No puzzles available", false);
			emptySign.setFormat("Courier New", 24, 0xFFFFFF, "center", 1, true);
			emptySign.x = body.x + (body.width - emptySign.width)/2;
			emptySign.y = body.y + (body.height - emptySign.height)/2;
			
			var chickens:FlxText = new FlxText(500,100,200,"Chickens Thrown:",false);
			chickens.setFormat("Courier New", 16, 0x000000, "left");
			var chickenNum:FlxText = new FlxText(500,125,125, new String(Elemental.achievements.getChickensThrown()),false);
			chickenNum.setFormat("Courier New", 16, 0xAA0000, "right", 0, true);
			this.add(chickens);
			this.add(chickenNum);
			
			var  monsters:FlxText = new FlxText(500,160,200,"Monsters Killed:",false);
			monsters.setFormat("Courier New", 16, 0x000000, "left");
			var mNum:FlxText = new FlxText(500,185,125, new String(Elemental.achievements.getMonstersKilled()),false);
			mNum.setFormat("Courier New", 16, 0xAA0000, "right", 0, true);
			this.add(monsters);
			this.add(mNum);
			
			var mapsCreated:FlxText = new FlxText(500,220,200,"Maps Created:",false);
			mapsCreated.setFormat("Courier New", 16, 0x000000, "left");
			var mapNum:FlxText = new FlxText(500,245,125, new String(Elemental.achievements.getMapsCreated()),false);
			mapNum.setFormat("Courier New", 16, 0xAA0000, "right", 0, true);
			this.add(mapsCreated);
			this.add(mapNum);
			
			var challengeBeat:FlxText = new FlxText(500,280,200,"Challenge Puzzles:",false);
			challengeBeat.setFormat("Courier New", 16, 0x000000, "left");
			var challNum:FlxText = new FlxText(500,305,125, new String(Elemental.achievements.getChallengesBeaten()),false);
			challNum.setFormat("Courier New", 16, 0xAA0000, "right", 0, true);
			this.add(challengeBeat);
			this.add(challNum);
			
			var mapsBeaten:FlxText = new FlxText(500,340,200,"Player Puzzles:",false);
			mapsBeaten.setFormat("Courier New", 16, 0x000000, "left");
			var bNum:FlxText = new FlxText(500,365,125, new String(Elemental.achievements.getPlayerMapsBeaten()),false);
			bNum.setFormat("Courier New", 16, 0xAA0000, "right", 0, true);
			this.add(mapsBeaten);
			this.add(bNum);
			
			var friendsBeated:FlxText = new FlxText(500,400,200,"Friend Puzzles:",false);
			friendsBeated.setFormat("Courier New", 16, 0x000000, "left");
			var fNum:FlxText = new FlxText(500,425,125, new String(Elemental.achievements.getFriendMapsBeaten()),false);
			fNum.setFormat("Courier New", 16, 0xAA0000, "right", 0, true);
			this.add(friendsBeated);
			this.add(fNum);
			
			var storyLevel:FlxText = new FlxText(500,460,200,"Story Level:",false);
			storyLevel.setFormat("Courier New", 16, 0x000000, "left");
			var sNum:FlxText = new FlxText(500,485,125, new String(Elemental.achievements.getStoryLevelReached()),false);
			sNum.setFormat("Courier New", 16, 0xAA0000, "right", 0, true);
			this.add(storyLevel);
			this.add(sNum);
			
			var title:ComponentTitle = new ComponentTitle("My Puzzles and Statistics", CONTAINER_START_X + 60, CONTAINER_START_Y - 50);
			add(title);
			
			createChallengeButtons();
		}
		
		private function createChallengeButtons():void {
			challenge1 = new FlxSprite(275, 150 + 20, Res.challengeFriends);
			challenge2 = new FlxSprite(275, 260 + 20, Res.challengeFriends);
			challenge3 = new FlxSprite(275, 370 + 20, Res.challengeFriends);
		}
		
		/**
		 * If a tab is clicked, make it focused, and do another request if necessary.
		 */
		public override function update():void {
			super.update();
			
			if (modalPopup) {
				if (challengePopup.finishedChallenging()) {
					this.remove(challengePopup, true);
					modalPopup = false;
				}
			} else {
				if (FlxG.mouse.justPressed()) {
					if (exitButton.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY) && !loading) {
						FlxG.switchState(new PlayerRoomState());
					}
					
					if (challenge1.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY)) {
						modalPopup = true;
						var xpos:int = (FlxG.width - ChallengeFriendsComponent.WIDTH)/2;
						var ypos:int = (FlxG.height - ChallengeFriendsComponent.HEIGHT)/2;
						challengePopup = new ChallengeFriendsComponent(mapID1, xpos, ypos);
						add(challengePopup);
					}
					if (challenge2.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY)) {
						modalPopup = true;
						var xpos2:int = (FlxG.width - ChallengeFriendsComponent.WIDTH)/2;
						var ypos2:int = (FlxG.height - ChallengeFriendsComponent.HEIGHT)/2;
						challengePopup = new ChallengeFriendsComponent(mapID2, xpos2, ypos2);
						add(challengePopup);
					}
					if (challenge3.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY)) {
						modalPopup = true;
						var xpos3:int = (FlxG.width - ChallengeFriendsComponent.WIDTH)/2;
						var ypos3:int = (FlxG.height - ChallengeFriendsComponent.HEIGHT)/2;
						challengePopup = new ChallengeFriendsComponent(mapID3, xpos3, ypos3);
						add(challengePopup);
					}
					
					if (prevPage.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY)) {
						requestNewPage(currentPage - 1);
					}
					
					if (nextPage.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY)) {
						requestNewPage(currentPage + 1);
					}
				}
			}
		}
		
		
		/**
		 * Called when the page arrows are clicked.
		 * Precondition: we already have data for this difficulty type.
		 * Does nothing if the requested page is invalid.
		 */
		private function requestNewPage(requestedPage:int):void {
			var totalPages:int = Math.ceil(listingArray.length / 5);
			if (requestedPage < 1 || requestedPage > totalPages) {
				return;
			}
			
			currentPage = requestedPage;
			listings.clear();
			remove(pageNum);
			remove(prevPage);
			remove(nextPage);
			
			updateListings(requestedPage);
		}
		
		
		/**
		 * Clears all items in the container and makes a request to server.
		 * Called when a tab is clicked or when this class is initialized.
		 * Adds loading graphic, resets current page num to 1.
		 */
		private function requestData():void {
			// clear the page
			listings.clear();
			remove(pageNum)
			remove(prevPage);
			remove(nextPage);
			remove(emptySign);
		
			add(loadingText);
			add(loadingSprite);
			loading = true;
			Client.getAllPuzzlesCreatedBy(Elemental.fbInfo.userID, loadData);
		}
		
		
		/**
		 * Called when our client has received data from the server.
		 * Removes loading graphic, creates a listing for five puzzles.
		 */
		private function loadData(e:Event):void {
			var maps:String = e.target.data;
			trace("returned " + e.target.data);
			
			if (maps == "no maps") {
				remove(loadingText);
				remove(loadingSprite);
				loading = false;
				add(emptySign);
				
				
				listingArray = new Array();
				
			} else {
				listingArray = maps.split("/");
				
				loading = false;
				remove(loadingText);
				remove(loadingSprite);
				updateListings(currentPage);
			}
		}
		
		/**
		 * Grabs the listings for the requested batch, and updates the footer.
		 * Precondition: assumes data exists.
		 */
		private function updateListings(pageNum:int):void {
			this.remove(challenge1, true);
			this.remove(challenge2, true);
			this.remove(challenge3, true);
			var startIndex:int = (pageNum-1)*3;
			for (var i:int = 0; i < 3; i++) {
				var xPos:int = body.x + 15;
				var yPos:int = body.y + (MyPuzzleListing.LISTING_HEIGHT * i) + ((i+1) * 15);
				
				if (startIndex + i >= listingArray.length || listingArray.length == 0) {
					break;
				}
				
				var spec:String = listingArray[startIndex + i];
				var specArray:Array = spec.split(":");
				
				if (i == 0) {
					mapID1 = specArray[0];
					this.add(challenge1);
				} else if (i == 1) {
					mapID2 = specArray[0];
					this.add(challenge2);
				} else if (i == 2) {
					mapID3= specArray[0];
					this.add(challenge3);
				}
				
				var listing:MyPuzzleListing = new MyPuzzleListing(specArray[2], specArray[1], specArray[8], spec, xPos, yPos);
				listings.add(listing);
			}
			
			var totalPages:int = Math.ceil(listingArray.length / 3);
			updateFooter(pageNum, totalPages);
			
		}
		
		/**
		 * Initializes footer text (but not added to stage)
		 */
		private function createPageFooter():void {
			pageNum = new FlxText(0, 0, body.width, "Page 1 of 15", false);
			pageNum.setFormat("Courier New", 26, 0x000000, "center", 0, true);
			pageNum.x = body.x + (body.width - pageNum.width)/2;
			pageNum.y = body.y + body.height - 10 - pageNum.height;
			
			prevPage = new FlxText(0, 0, 100, "<<", false);
			prevPage.setFormat("Courier New", 26, 0x000000, "right", 0, true);
			prevPage.x = body.x + 10;
			prevPage.y = pageNum.y;
			
			nextPage = new FlxText(0, 0, 100, ">>", false);
			nextPage.setFormat("Courier New", 26, 0x000000, "left", 0, true);
			nextPage.x = body.x + body.width - 10 - nextPage.width;
			nextPage.y = pageNum.y;
		}
		
		/**
		 * Updates footer text depending on current page.
		 */
		private function updateFooter(currPage:int, totalPages:int):void {
			pageNum.text = "Page " + currPage + " of " + totalPages;
			add(pageNum);
			
			if (currPage > 1) add(prevPage);
			if (currPage < totalPages) add(nextPage);
		}
		
	}
}